#include "window.h"
#include "opencv/highgui.h"

#include <iostream>

/***** Sous Virtual Box *****/
#define KEY_Q 1048689	// quitter
#define KEY_E 1048677	// enregistrer
#define KEY_S 1048691	// split
#define KEY_M 1048685	// split et merge
#define KEY_H 1048680	// switcher l'homogénéité
#define KEY_C 1048675	// switcher la couleur
#define KEY_A 1048673	// switcher alea et moyenne
#define KEY_R 1048690	// switcher l'algo de merge

/***** Installation normale *****/
#define KEY2_Q 113		// quitter
#define KEY2_E 101		// enregistrer
#define KEY2_S 115		// split
#define KEY2_M 109		// split et merge
#define KEY2_H 104		// switcher l'homogénéité
#define KEY2_C 99		// switcher la couleur
#define KEY2_A 97		// switcher alea et moyenne
#define KEY2_R 114		// switch l'algo de merge

Window::Window(const char* imgPath)
{
	mainImg = new Image(imgPath);
	
	//cvNamedWindow("Split & Merge", CV_WINDOW_AUTOSIZE);
	cvNamedWindow("Split & Merge", 0);
	
	cvCreateTrackbar("Split : taille en pixels : ", "Split & Merge", 0, 200, NULL);
	cvCreateTrackbar("Split : seuil d'homogénéité : ", "Split & Merge", 0, 255, NULL);
	cvCreateTrackbar("Merge : seuil d'homogénéité : ", "Split & Merge", 0, 255, NULL);
	
	cvSetTrackbarPos("Split : taille en pixels : ", "Split & Merge", mainImg->GetSplitMinPixel());
	cvSetTrackbarPos("Split : seuil d'homogénéité : ", "Split & Merge", mainImg->GetSplitThreshold());
	cvSetTrackbarPos("Merge : seuil d'homogénéité : ", "Split & Merge", mainImg->GetMergeThreshold());
	
	cvShowImage("Split & Merge", mainImg->GetImg());
	imgShow = 0;
	
	// Affichage console
	std::cout << "            SPLIT & MERGE" << std::endl;
	std::cout << "            -------------" << std::endl << std::endl;
	
	std::cout << "q : Quitte l'application." << std::endl;
	std::cout << "e : Enregistre l'image actuellement affiche." << std::endl << std::endl;
	
	std::cout << "Commande de plit et de merge : " << std::endl;
	std::cout << "     - s : Lance le split et affiche le resultat." << std::endl;
	std::cout << "     - m : Lance le split et le merge et affiche le resultat du merge." << std::endl << std::endl;
	
	std::cout << "Option de split et de merge : " << std::endl;
	std::cout << "     - h : Switch entre les deux methode de test d'homogeneite possible." << std::endl;
	std::cout << "           Par defaut c'est le test d'homogeneite selon la couleur du" << std::endl;
	std::cout << "           premier pixel de la region qui est utilise." << std::endl;
	std::cout << "     - r : Switch entre les deux methodes de merge (par defaut on merge" << std::endl;
	std::cout << "           les grandes zones en premier)." << std::endl;
	std::cout << "     - a : Switch entre un coloriage aleatoire et un coloriage selon la" << std::endl;
	std::cout << "           moyenne des couleurs de l'image d'origine. Par defaut c'est un" << std::endl;
	std::cout << "           coloriage par moyenne." << std::endl << std::endl;
	/*std::cout << "     - c : Switch entre un resultat en couleur ou en noir et blanc." << std::endl;
	std::cout << "           Par defaut il est en couleur." << std::endl << std::endl;*/
	
	std::cout << "Details sur les trois sliders :" << std::endl;
	std::cout << "     - Split : taille en pixels -> Cela permet de regler la taille de la plus" << std::endl;
	std::cout << "               petite coupe possible lors du split. En dessous de cette taille" << std::endl;
	std::cout << "               le test d'homogeneite n'est plus realise et il n'y a plus de" << std::endl;
	std::cout << "               decoupe." << std::endl;
	std::cout << "     - Split : seuil d'homogeneite -> Plus le seuil est petit plus les regions" << std::endl;
	std::cout << "               seront consideree comme non homogenes." << std::endl;
	std::cout << "     - Merge : seuil d'homogeneite -> Plus le seuil est petit plus les regions" << std::endl;
	std::cout << "               voisines vont être considere comme non homogenes entre elles." << std::endl << std::endl;
	
	std::cout << "Pour plus de detail sur les structures et les methodes utilisees se referer au" << std::endl;
	std::cout << "rapport fournis avec :) !" << std::endl << std::endl;
}

Window::~Window()
{
	delete mainImg;
	cvDestroyWindow("Split & Merge");
}

void Window::KeyboardHandler()
{
	while(1)
	{
		int key = cvWaitKey(0);
		if (key == KEY_Q || key == KEY2_Q)
		{
			std::cout << "Q : Vous quittez l'application. Aurevoir !" << std::endl;
			break;
		}
			
		if (KEY_M == key || KEY2_M == key)
		{
			std::cout << "M : Split & Merge de l'image." << std::endl;
			mainImg->SetSplitMinPixel(cvGetTrackbarPos("Split : taille en pixels : ", "Split & Merge"));
			mainImg->SetSplitThreshold(cvGetTrackbarPos("Split : seuil d'homogénéité : ", "Split & Merge"));
			mainImg->SetMergeThreshold(cvGetTrackbarPos("Merge : seuil d'homogénéité : ", "Split & Merge"));
			mainImg->Split();
			if (mainImg->GetReverseMerge())
				cvShowImage("Split & Merge", mainImg->ReverseMerge());
			else
				cvShowImage("Split & Merge", mainImg->Merge());

			imgShow = 2;
		} 
		else if (KEY_S == key || KEY2_S == key)
		{
			std::cout << "S : Split de l'image." << std::endl;
			mainImg->SetSplitMinPixel(cvGetTrackbarPos("Split : taille en pixels : ", "Split & Merge"));
			mainImg->SetSplitThreshold(cvGetTrackbarPos("Split : seuil d'homogénéité : ", "Split & Merge"));
      mainImg->SetMergeThreshold(cvGetTrackbarPos("Merge : seuil d'homogénéité : ", "Split & Merge"));
			cvShowImage("Split & Merge", mainImg->Split());
			imgShow = 1;
		}
		else if (KEY_E == key || KEY2_E == key)
		{
			if (imgShow == 0)
				std::cout << "E : Ceci est l'image originel, elle n'a pas besoin d'etre reenregistre." << std::endl;
			else if (imgShow == 1)
			{
				std::cout << "E : Vous enregistrez l'image représentant la grille de split." << std::endl;
				cvSaveImage(NameFile(true).c_str(), mainImg->GetSplitImg());
				std::cout << "E -> Votre image est bien enregistree a l'endroit suivant : " << NameFile(true) << std::endl;
			}
			else
			{
				std::cout << "E : Vous enregistrez l'image final." << std::endl;
				cvSaveImage(NameFile(false).c_str(), mainImg->GetMergeImg());
				std::cout << "E -> Votre image est bien enregistree a l'endroit suivant : " << NameFile(false) << std::endl;
			}
		}
		else if (KEY_A == key || KEY2_A == key)
		{
			if (mainImg->GetAleaColorResult())
			{
				std::cout << "A : Vous passez a un coloriage par moyenne de couleur." << std::endl;
				mainImg->SetAleaColorResult(false);
			}
			else
			{
				std::cout << "A : Vous passez a un coloriage aleatoire." << std::endl;
				mainImg->SetAleaColorResult(true);
			}
		}
		else if (KEY_H == key || KEY2_H == key)
		{
			if (mainImg->GetHomogeneousFct() == 1)
			{
				std::cout << "H : Vous passez a un test d'homogeneite par moyenne." << std::endl;
				mainImg->SetHomogeneousFct(2);
			}
			else
			{
				std::cout << "H : Vous passez a un test d'homogeneite selon la valeur du premier pixel de la zone." << std::endl;
				mainImg->SetHomogeneousFct(1);
			}
		}
		else if (KEY_R == key || KEY2_R == key)
		{
			if (mainImg->GetReverseMerge())
			{
				std::cout << "R : Vous passez à la méthode de merge qui commence par les grandes zones." << std::endl;
				mainImg->SetReverseMerge(false);
			}
			else
			{
				std::cout << "R : Vous passez à la méthode de merge qui commence par les petites zones." << std::endl;
				mainImg->SetReverseMerge(true);
			}
		}
		/*else if (KEY_C == key || KEY2_C == key)
		{
			if (mainImg->GetColorResult())
			{
				std::cout << "C : Vous passez a un resultat en noir et blanc." << std::endl;
				mainImg->SetColorResult(false);
			}
			else
			{
				std::cout << "C : Vous passez a un resultat en couleur." << std::endl;
				mainImg->SetColorResult(true);
			}			
		}*/
	}
}

std::string Window::NameFile(bool split)
{
	size_t posLastSlash = mainImg->GetImgPath().rfind("/");
	std::string fileName = mainImg->GetImgPath().substr(posLastSlash + 1, mainImg->GetImgPath().size());
	std::string finalPath;
	
	int splitPixel = mainImg->GetSplitMinPixel();
	int splitThreshold = mainImg->GetSplitThreshold();
	int mergeThreshold = mainImg->GetMergeThreshold();
	
	std::ostringstream ossFileName;
	if (mainImg->GetColorResult())			// Si on est en couleur
		if (mainImg->GetAleaColorResult())	// Si on est en couleur aleatoire
			if (mainImg->GetReverseMerge())	// Si on utilise le reverseMerge()
				ossFileName << "h" << mainImg->GetHomogeneousFct() << "_rm_a_" << splitPixel << "_" << splitThreshold << "_" << mergeThreshold << "_" << fileName;
			else
				ossFileName << "h" << mainImg->GetHomogeneousFct() << "_a_" << splitPixel << "_" << splitThreshold << "_" << mergeThreshold << "_" << fileName;
		else
			if (mainImg->GetReverseMerge())
				ossFileName << "h" << mainImg->GetHomogeneousFct() << "_rm_" << splitPixel << "_" << splitThreshold << "_" << mergeThreshold << "_" << fileName;
			else
				ossFileName << "h" << mainImg->GetHomogeneousFct() << "_" << splitPixel << "_" << splitThreshold << "_" << mergeThreshold << "_" << fileName;
	else
		if (mainImg->GetAleaColorResult())
			if (mainImg->GetReverseMerge())
				ossFileName << "h" << mainImg->GetHomogeneousFct() << "_rm_nb_a_" << splitPixel << "_" << splitThreshold << "_" << mergeThreshold << "_" << fileName;
			else
				ossFileName << "h" << mainImg->GetHomogeneousFct() << "_nb_a_" << splitPixel << "_" << splitThreshold << "_" << mergeThreshold << "_" << fileName;
		else
			if (mainImg->GetReverseMerge())
				ossFileName << "h" << mainImg->GetHomogeneousFct() << "_rm_nb_" << splitPixel << "_" << splitThreshold << "_" << mergeThreshold << "_" << fileName;
			else
				ossFileName << "h" << mainImg->GetHomogeneousFct() << "_nb_" << splitPixel << "_" << splitThreshold << "_" << mergeThreshold << "_" << fileName;
			
	
	
	if (split)
		finalPath = "../split/" + ossFileName.str();
	else
		finalPath = "../merge/" + ossFileName.str();
	
	return finalPath;
}

